﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
using Critex.Helpers;
using Critex.Models;
using Critex.ViewModels;
using HtmlArea = Critex.Models.HtmlArea;
using HtmlCollectionArea = Critex.Models.HtmlCollectionArea;
using ImageArea = Critex.Models.ImageArea;
using ImageCollectionArea = Critex.Models.ImageCollectionArea;

namespace Critex.Controllers
{
    public class DashboardController : Controller
    {

        public class AuthorizeEditorAttribute : ActionFilterAttribute
        {
            public override void OnActionExecuting(ActionExecutingContext filterContext)
            {

                if (filterContext.HttpContext.Session == null || filterContext.HttpContext.Session["User"] == null)
                {
                    var redirectTargetDictionary = new RouteValueDictionary();
                    redirectTargetDictionary.Add("action", "SignIn");
                    redirectTargetDictionary.Add("controller", "Dashboard");

                    filterContext.Result = new RedirectToRouteResult(redirectTargetDictionary);
                }

                base.OnActionExecuting(filterContext);
            }

        }

        public ActionResult SignIn()
        {
            return View("SignIn");
        }

        [HttpPost]
        public ActionResult SignIn(string username, string password)
        {
            var container = ConnectionHelper.GetContainer();

            if (container.Users.Any(u => u.Username == username && u.Password == password))
            {
                Session["User"] = true;
                return RedirectToAction("Index");
            }
            else
            {
                return RedirectToAction("SignIn");
            }
        }

        [AuthorizeEditor]
        public ActionResult Index()
        {
            var container = ConnectionHelper.GetContainer();

            var model = new DashboardViewModel();
            PrepareDashboardViewModel(model, container);

            return View(model);
        }

        private static void PrepareDashboardViewModel(DashboardViewModel model, ModelContainer container)
        {
            model.TopLevelSections = container.Sections.Where(s => !s.ParentSections.Any());
        }

        [AuthorizeEditor]
        public ActionResult ModifySection(int id)
        {

            var container = ConnectionHelper.GetContainer();

            var model = new DashboardModifySectionViewModel();
            PrepareDashboardViewModel(model, container);

            model.SelectedSection = container.Sections.First(s => s.Id == id);

            return View(model);
        }

        [AuthorizeEditor]
        public ActionResult AddNewImageAreaToCollection(int collectionId, int sectionId)
        {

            var container = ConnectionHelper.GetContainer();

            var model = new DashboardUploadImageViewModel();
            PrepareDashboardViewModel(model, container);

            model.TargetCollection =
                container.ContentAreas.OfType<Models.ImageCollectionArea>().First(a => a.Id == collectionId);

            model.SectionId = sectionId;

            return View("UploadImage", model);
        }

        [AuthorizeEditor]
        public ActionResult DeleteHtmlAreaFromCollection(int collectionId, int areaId, int sectionId)
        {
            var container = ConnectionHelper.GetContainer();

            var collection = container.ContentAreas.OfType<Models.HtmlCollectionArea>().First(a => a.Id == collectionId);
            var area = container.ContentAreas.OfType<Models.HtmlArea>().First(a => a.Id == areaId);
            collection.HtmlAreas.Remove(area);
            container.DeleteObject(area);

            container.SaveChanges();

            return RedirectToAction("ModifySection", new RouteValueDictionary() { { "id", sectionId } });
        }

        [AuthorizeEditor]
        public ActionResult AddNewHtmlAreaToCollection(int collectionId, int sectionId)
        {
            var container = ConnectionHelper.GetContainer();

            var collection = container.ContentAreas.OfType<Models.HtmlCollectionArea>().First(a => a.Id == collectionId);
            var area = HtmlArea.CreateHtmlArea(0, string.Empty);
            collection.HtmlAreas.Add(area);
            container.ContentAreas.AddObject(area);

            container.SaveChanges();

            return RedirectToAction("ModifySection", new RouteValueDictionary() { { "id", sectionId } });
        }

        [HttpPost, ValidateInput(false),
        AuthorizeEditor]
        public ActionResult UploadImage(int areaId, int collectionId, int sectionId, HttpPostedFileBase file, string shortDescription, string longDescription)
        {

            //TODO: support for more filetypes.

            //TODO: validation of image.

            var fileName = DateTime.Now.ToString("yyyy-MM-dd-hh-mm-ss-fffffff") + ".jpg";
            var filePath = Path.Combine(Request.MapPath("~/Uploads"), fileName);
            file.SaveAs(filePath);

            var container = ConnectionHelper.GetContainer();

            ImageArea area;
            if (areaId > -1)
            {
                area = container.ContentAreas.OfType<ImageArea>().First(a => a.Id == areaId);
            }
            else
            {
                area = ImageArea.CreateImageArea(0, string.Empty);
                container.ContentAreas.AddObject(area);
            }

            if (Request.Url != null)
            {
                area.Location = Request.Url.GetLeftPart(UriPartial.Authority) + "/Uploads/" + fileName;
            }

            area.ShortDescription = shortDescription;
            area.LongDescription = longDescription;

            if (collectionId > -1)
            {
                var collection = container.ContentAreas.OfType<Models.ImageCollectionArea>().First(a => a.Id == collectionId);
                collection.ImageAreas.Add(area);
            }

            container.SaveChanges();

            return RedirectToAction("ModifySection", new RouteValueDictionary() { { "id", sectionId } });
        }

        [AuthorizeEditor]
        public ActionResult DeleteImageArea(int id, int sectionId)
        {
            var container = ConnectionHelper.GetContainer();

            var area = container.ContentAreas.First(a => a.Id == id);
            container.DeleteObject(area);

            container.SaveChanges();

            return RedirectToAction("ModifySection", new RouteValueDictionary() { { "id", sectionId } });
        }

        [HttpPost, ValidateInput(false), AuthorizeEditor]
        public ActionResult ModifyHtmlArea(FormCollection collection)
        {

            var areaId = int.Parse(collection["areaId"]);
            var sectionId = int.Parse(collection["sectionId"]);
            var content = collection["content" + areaId];

            var container = ConnectionHelper.GetContainer();

            var area = container.ContentAreas.OfType<Models.HtmlArea>().First(a => a.Id == areaId);
            area.Html = content;

            container.SaveChanges();

            return RedirectToAction("ModifySection", new RouteValueDictionary() { { "id", sectionId } });

        }

        [HttpPost, AuthorizeEditor]
        public ActionResult ModifyAddressArea(string address, int areaId, int sectionId)
        {

            var container = ConnectionHelper.GetContainer();

            var area = container.ContentAreas.OfType<Models.AddressArea>().First(a => a.Id == areaId);
            area.Address = address;

            container.SaveChanges();

            return RedirectToAction("ModifySection", new RouteValueDictionary() { { "id", sectionId } });
        }

        [AuthorizeEditor]
        public ActionResult ModifyImageArea(int areaId, int sectionId)
        {

            var container = ConnectionHelper.GetContainer();

            var model = new DashboardUploadImageViewModel();
            PrepareDashboardViewModel(model, container);

            var area = (ImageArea)container.ContentAreas.First(a => a.Id == areaId);
            model.LongDescription = area.LongDescription;
            model.ShortDescription = area.ShortDescription;

            var settings = container.Settings.First();

            model.StyleLocation = settings.StyleLocation;

            model.SectionId = sectionId;

            return View("UploadImage", model);
        }
    }
}
